package com.syh.jn.scm.infrastructure.repository.impl.supplier.purchase;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseReturnOrder;
import com.syh.jn.scm.domain.supplier.entity.purchase.PurchaseReturnOrderItem;
import com.syh.jn.scm.domain.supplier.repository.purchase.PurchaseReturnOrderRepository;
import com.syh.jn.scm.dto.supplier.purchase.PurchaseReturnOrderVo;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseReturnOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.purchase.PurchaseReturnOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 采购退货单仓储
 */
@Repository
public class PurchaseReturnOrderRepositoryImpl extends AbstractAggregateRepository<PurchaseReturnOrder, PurchaseReturnOrderModel, Long> implements PurchaseReturnOrderRepository {
  /**
   * 新增采购退货单
   *
   * @param purchaseReturnOrder
   * @return
   */
  @Override
  public Long add(PurchaseReturnOrder purchaseReturnOrder) {
    Long id = super.add(purchaseReturnOrder);
    this.saveOrderItems(id, purchaseReturnOrder.getItems());
    return id;
  }

  /**
   * 修改采购退货单
   *
   * @param purchaseReturnOrder
   */
  @Override
  public void update(PurchaseReturnOrder purchaseReturnOrder) {
    super.update(purchaseReturnOrder);
    //删除订单项
    this.removeItem(purchaseReturnOrder);
    //保存新的采购退货订单项
    this.saveOrderItems(purchaseReturnOrder.getId(), purchaseReturnOrder.getItems());
  }

  @Override
  public PurchaseReturnOrder getById(Long id) {
    PurchaseReturnOrder purchaseReturnOrder =  super.getById(id);
    if (purchaseReturnOrder == null) {
      return purchaseReturnOrder;
    }
    purchaseReturnOrder.setItems(this.getItemsByPurchaseReturnOrderId(id));
    return purchaseReturnOrder;
  }

  /**
   * 删除订单项
   *
   * @param purchaseReturnOrder
   */
  private void removeItem(PurchaseReturnOrder purchaseReturnOrder) {
    String hql = "from PurchaseReturnOrderItemModel model where model.purchaseReturnOrderId = ?";
    List<PurchaseReturnOrderItemModel> itemModelList = (List<PurchaseReturnOrderItemModel>) this.hibernateTemplate.find(hql, purchaseReturnOrder.getId());
    itemModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  /**
   * 保存当前采购退货订单对应的订单项
   *
   * @param purchaseReturnOrderId
   * @param items
   */
  private void saveOrderItems(Long purchaseReturnOrderId, List<PurchaseReturnOrderItem> items) {
    ValidationUtils.validate(items);
    items.stream().forEach(item -> {
      PurchaseReturnOrderItemModel itemModel = new PurchaseReturnOrderItemModel();

      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, item.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if(goodsModel.getGoodsBrandId() != null){
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if(goodsModel.getCategoryId() != null){
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      PurchaseReturnOrderModel purchaseReturnOrderModel = this.hibernateTemplate.get(PurchaseReturnOrderModel.class, purchaseReturnOrderId);

      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setPurchaseReturnOrderId(purchaseReturnOrderId);
      itemModel.setBusinessEntityId(purchaseReturnOrderModel.getBusinessEntityId());

      //在仓储层冗余是为了安全和数据的准确
      itemModel.setGoodsName(goodsModel.getName());
      itemModel.setSpecName(goodsModel.getSpecName());
      itemModel.setGoodsCode(goodsModel.getCode());
      itemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      itemModel.setConversionRate(goodsModel.getConversionRate());
      itemModel.setCodeBar(goodsModel.getCodeBar());
      itemModel.setUnits(goodsModel.getUnits());
      itemModel.setCategoryId(goodsModel.getCategoryId());
      itemModel.setCategoryName(goodsCategoryModel.getName());
      itemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      itemModel.setGoodsBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      itemModel.setGoodsBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(itemModel);
    });
  }

  /**
   * 删除采购退货单
   *
   * @param purchaseReturnOrder
   */
  @Override
  public void remove(PurchaseReturnOrder purchaseReturnOrder) {
    //删除主项
    super.removeById(purchaseReturnOrder.getId());
    //删除明细
    this.removeItem(purchaseReturnOrder);
  }

  /**
   * 根据id拿到明细
   *
   * @param id
   * @return
   */
  @Override
  public List<PurchaseReturnOrderItem> getItem(Long id) {
    String hql = "from PurchaseReturnOrderItemModel model where model.purchaseReturnOrderId = ?";
    List<PurchaseReturnOrderItemModel> model = (List<PurchaseReturnOrderItemModel>) this.hibernateTemplate.find(hql, id);
    List<PurchaseReturnOrderItem> itemList = new ArrayList<>();
    model.stream().forEach(item -> {
      PurchaseReturnOrderItem orderItem = new PurchaseReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });
    return itemList;
  }

  @Override
  public PurchaseReturnOrderItem getItemByItemId(Long itemId) {
    PurchaseReturnOrderItemModel itemModel = this.hibernateTemplate.get(PurchaseReturnOrderItemModel.class,itemId);
    PurchaseReturnOrderItem item = new PurchaseReturnOrderItem();
    ExtBeanUtils.copyProperties(itemModel, item);
    return item;
  }

  @Override
  public List<PurchaseReturnOrderItem> getItemsByPurchaseReturnOrderId(Long returnOrderId) {
    String hql = "from PurchaseReturnOrderItemModel model where model.purchaseReturnOrderId = ?";

    List<PurchaseReturnOrderItemModel> model = (List<PurchaseReturnOrderItemModel>) this.hibernateTemplate.find(hql, returnOrderId);
    List<PurchaseReturnOrderItem> itemList = new ArrayList<>();
    model.stream().forEach(item -> {
      PurchaseReturnOrderItem orderItem = new PurchaseReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });
    return itemList;
  }

  /**
   * 根据归属id获取明细
   *
   * @param returnOrderIds
   * @return
   */
  @Override
  public List<PurchaseReturnOrderItem> getItemsByPurchaseReturnOrderIds(Long[] returnOrderIds) {
    String hql = "from PurchaseReturnOrderItemModel model where model.purchaseReturnOrderId in (:returnOrderIds)";

    Query query = buildQuery(hql);
    query.setParameterList("returnOrderIds", returnOrderIds);
    List<PurchaseReturnOrderItemModel> itemModelList = query.list();
    List<PurchaseReturnOrderItem> itemList = new ArrayList<>();
    itemModelList.stream().forEach(item -> {
      PurchaseReturnOrderItem orderItem = new PurchaseReturnOrderItem();
      ExtBeanUtils.copyProperties(item, orderItem);
      itemList.add(orderItem);
    });
    return itemList;
  }

  /**
   * 取消订单
   *
   * @param purchaseReturnOrder
   */
  @Override
  public void cancel(PurchaseReturnOrder purchaseReturnOrder) {
    super.update(purchaseReturnOrder);
  }

  /**
   * 上传单据图片
   *
   * @param order
   */
  @Override
  public void upload(PurchaseReturnOrder order) {
    super.update(order);
  }

  /**
   * 确认订单
   *
   * @param order
   */
  @Override
  public void confirmOrder(PurchaseReturnOrder order) {
    super.update(order);
  }

  @Override
  public void updateOrderAndItems(PurchaseReturnOrder order) {
    PurchaseReturnOrderModel orderModel = this.hibernateTemplate.get(PurchaseReturnOrderModel.class, order.getId());
    if(orderModel == null){
      throw new DataModelException("订单不存在");
    }
    ExtBeanUtils.copyProperties(order, orderModel);
    this.hibernateTemplate.update(orderModel);
    //更新订单项
    order.getItems().forEach(orderItem -> {
      PurchaseReturnOrderItemModel model = this.hibernateTemplate.get(PurchaseReturnOrderItemModel.class, orderItem.getId());
      if(model == null){
        throw new DataModelException("对应明细不存在");
      }
      ExtBeanUtils.copyProperties(orderItem, model);
      this.hibernateTemplate.update(model);
    });
  }

  /**
   * 根据服务商id删除订单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from PurchaseReturnOrderItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from PurchaseReturnOrderModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  @Override
  protected SQL getViewSql() {
    return new SQL() {{
      SELECT(
              SQLAliasGenerateUtil.aliasGenerate(PurchaseReturnOrderModel.class, "purchaseRet", null),
              "pur.code AS purchaseOrderCode",
              "dict.NAME AS returnReasonName",
              "up.NAME AS upStreamCompanyName"
      );
      FROM("T_PUR_PURCHASE_RETURN_ORDER purchaseRet");
      LEFT_OUTER_JOIN("T_PUR_PURCHASE_ORDER pur on pur.ID = purchaseRet.PURCHASE_ORDER_ID");
      LEFT_OUTER_JOIN("T_BASE_DICT dict on dict.ID = purchaseRet.RETURN_REASON_ID");
      LEFT_OUTER_JOIN("T_BASE_UPSTREAM up on up.ID = purchaseRet.UP_STREAM_COMPANY_ID");
    }};
  }

  @Override
  protected Class getViewObject() {
    return PurchaseReturnOrderVo.class;
  }

  @Override
  protected BaseResolve getViewWrapperResolve(Wrapper wrapper) {
    Map<String, String> params = new HashMap<>();
    params.put("returnCode", "purchaseRet.RETURN_CODE");
    params.put("id", "purchaseRet.ID");
    params.put("extCode","purchaseRet.EXT_CODE");
    params.put("name","up.NAME");
    params.put("returnOrdState", "purchaseRet.RETURN_ORD_STATE");
    params.put("deliveryState", "purchaseRet.DELIVERY_STATE");
    params.put("collectState", "purchaseRet.COLLECT_STATE");
    params.put("logisticsCompanyId", "purchaseRet.LOGISTICS_COMPANY_ID");
    params.put("statementId", "purchaseRet.STATEMENT_ID");
    params.put("deliName", "purchaseRet.DELI_NAME");
    params.put("deliTel", "purchaseRet.DELI_TEL");
    params.put("remark", "purchaseRet.REMARK");
    params.put("upStreamCompanyId", "purchaseRet.UP_STREAM_COMPANY_ID");
    params.put("businessEntityId", "purchaseRet.BUSINESS_ENTITY_ID");
    params.put("inputDateTimestamp","purchaseRet.INPUT_DATE_TIMESTAMP");
    ResolveToSQL parse = new ResolveToSQL(wrapper, (propertyName) -> {
      return params.get(propertyName);
    });
    return parse;
  }

  /**
   * 判断采购退货项是否存在该商品
   *
   * @param column
   * @param id
   * @return
   */
  @Override
  public boolean purReturnItemExistsById(String column, Long id) {
    StringBuffer hql = new StringBuffer("SELECT COUNT(*) FROM PurchaseReturnOrderItemModel where ").append(column).append(" = ").append(id);
    this.getLogger().debug(hql.toString());
    Query query = buildQuery(hql);
    return ((Long) query.uniqueResult()).intValue() > 0;
  }
}
